#ifndef _TIMER_H
#define _TIMER_H 

#include <types.h>
#include <ioctl.h>

typedef void (*timer_callback_t)(void);

#define MAJOR_TIMER				(3)

#define TIMER_IO_TYPE			't'
#define TIMER_IO_START			_IO(TIMER_IO_TYPE, 1)
#define TIMER_IO_STOP			_IO(TIMER_IO_TYPE, 2)
#define TIMER_IO_SET_INTERVAL	_IOW(TIMER_IO_TYPE, 3, uint64_t *)
#define TIMER_IO_GET_INTERVAL	_IOR(TIMER_IO_TYPE, 4, uint64_t *)
#define TIMER_IO_SET_TYPE		_IOW(TIMER_IO_TYPE, 5, uint32_t)
#define TIMER_IO_GET_TYPE		_IOR(TIMER_IO_TYPE, 6, uint32_t)
#define TIMER_IO_SET_CALLBACK	_IOW(TIMER_IO_TYPE, 7, timer_callback_t)
#define TIMER_IO_GET_TIME		_IOR(TIMER_IO_TYPE, 8, uint64_t *)

#define TIMER_TYPE_AUTORELOAD	(0)	
#define TIMER_TYPE_ONESHOT		(1)

#define TIMER_FLAGS_ONESHOT		(1)

struct timer {
	unsigned int flags;
	unsigned int interval;
	void *membase;
	void *priv;
	struct device *dev;
};

struct timer_driver;

struct timer_operations {
    int  (*startup)(struct timer *tm);
    void (*shutdown)(struct timer *tm);
    int  (*start)(struct timer *tm);
    int  (*stop)(struct timer *tm);
    int  (*ioctl)(struct timer *tm, unsigned int cmd, unsigned int arg);
	int  (*match)(struct device *dev, struct timer_driver *tm_drv);
	int  (*probe)(struct timer *tm, struct timer_driver *tm_drv);
	int  (*set_interval)(struct timer *tm, uint64_t interval);	
	int64_t (*get_interval)(struct timer *tm);
	int  (*set_type)(struct timer *tm, unsigned int type);
	int  (*get_type)(struct timer *tm);
	int  (*set_callback)(struct timer *tm, timer_callback_t callback);
	int64_t (*get_time)(struct timer *tm);
};

struct timer_driver {
	struct timer_operations *ops;
	struct driver *drv;
};

#define device_to_timer(dev)			((dev)->priv)
#define driver_to_timer_driver(drv)		((drv)->priv)
#define timer_to_device(tm)				((tm)->dev)
#define timer_driver_to_driver(tm_drv)	((tm_drv)->drv)

#define device_to_timer_driver(dev)		(driver_to_timer_driver(device_to_driver(dev)))

extern struct device_operations timer_ops;

#endif /* _TIMER_H */

